1 00:00:00,330 --> 00:00:00,840 All right. 2 00:00:00,840 --> 00:00:05,850 So let's go ahead and get started scripting the Obi generation for our project. 3 00:00:05,880 --> 00:00:10,740 Now since different players are going to be at different areas in the Obi, I want to go ahead and generate 4 00:00:10,740 --> 00:00:16,140 the Obi on the client side, but have every single player in the server generate the same Obi. 5 00:00:16,170 --> 00:00:21,120 This means we're going to have to generate a seed for each server that every client is going to use 6 00:00:21,120 --> 00:00:26,430 to randomly generate their Obi, and we're going to store this randomly generated seed inside of that 7 00:00:26,430 --> 00:00:28,530 number value inside of replicated storage. 8 00:00:28,530 --> 00:00:33,870 So all of the players in our game can access this seed and then set up their random number generators 9 00:00:33,870 --> 00:00:34,770 using this seed. 10 00:00:34,770 --> 00:00:37,740 So every single player is going to generate the same Obi. 11 00:00:38,280 --> 00:00:41,550 So we're going to have to generate this random number on the server. 12 00:00:41,550 --> 00:00:46,800 So we can create a new module script inside of server script service to act as our service. 13 00:00:46,800 --> 00:00:52,170 And I'm going to use a custom template that I've created which is attached to this lecture. 14 00:00:52,170 --> 00:00:56,520 Just so I don't have to sit here and type out all of these comments and stuff, it makes it really easy. 15 00:00:56,520 --> 00:01:00,480 And then I can use the shortcut of control shift and R to rename this. 16 00:01:00,480 --> 00:01:03,300 And we're going to call this our seed service. 17 00:01:03,300 --> 00:01:06,030 And then we can rename it in the workspace as well. 18 00:01:06,840 --> 00:01:12,660 And all this is going to do is grab that number value inside a replicated storage and update the value 19 00:01:12,660 --> 00:01:14,160 to a random number. 20 00:01:15,650 --> 00:01:18,530 So we can go ahead and create a new random data type. 21 00:01:18,530 --> 00:01:19,820 I'll just call this RNG. 22 00:01:21,320 --> 00:01:26,060 And then we can also get a reference to that number, value and replicated storage, which is called 23 00:01:26,060 --> 00:01:26,630 seed. 24 00:01:26,630 --> 00:01:30,980 And we're only going to need an initialize function for this service because we're just going to set 25 00:01:30,980 --> 00:01:33,410 seed dot value equal to RNG. 26 00:01:33,680 --> 00:01:36,170 And we'll just get a random number. 27 00:01:36,170 --> 00:01:42,080 And now we have generated the random seed for a particular server whenever this code is going to execute. 28 00:01:42,320 --> 00:01:46,460 Now this means we can go ahead and create a new script and start a starter player scripts. 29 00:01:46,460 --> 00:01:52,730 Inside of the handler section we'll create another new module and I'm going to call this my RB generation 30 00:01:52,730 --> 00:01:53,510 handler. 31 00:01:53,510 --> 00:01:57,230 And again I'll just paste in that exact same template I've got. 32 00:01:57,230 --> 00:02:01,070 And we'll rename this to RB Generation handler. 33 00:02:02,790 --> 00:02:06,630 Now, how this is going to work is the player's character is going to spawn here, and we're going to 34 00:02:06,630 --> 00:02:09,720 check the distance of the player's character away from this point. 35 00:02:09,720 --> 00:02:14,880 So we're going to set like a distance or a range that once a player gets inside of that range, then 36 00:02:14,880 --> 00:02:21,510 we're going to generate more sections of the Abbey and we can set it to something like 120 or 100 studs. 37 00:02:21,510 --> 00:02:26,790 So when the player is within 100 studs of this first part, we're going to generate the first Abbey 38 00:02:26,790 --> 00:02:27,360 model. 39 00:02:27,360 --> 00:02:31,140 And then we're going to update that position to the end of that Abbey model. 40 00:02:31,140 --> 00:02:35,730 And if the player is within 100 studs of the end of that Abbey model, then we'll generate the next 41 00:02:35,730 --> 00:02:40,680 one and we'll check the distance from that one and so forth, until the player is outside of that range. 42 00:02:40,680 --> 00:02:44,640 And when they are outside of that range, then we don't need to generate any more Abbey models. 43 00:02:44,640 --> 00:02:50,370 So that means we're going to have to constantly check the player's distance from these different parts 44 00:02:50,370 --> 00:02:53,130 that are going to be here or inside of our Abbey model. 45 00:02:53,130 --> 00:02:55,620 So that means we're going to need the run service, right? 46 00:02:55,620 --> 00:02:57,480 So we'll get the run service. 47 00:03:00,790 --> 00:03:04,210 We're also going to need replicated storage to get access to our seed. 48 00:03:06,500 --> 00:03:10,520 We'll also get the player service so we can get references to our player's character. 49 00:03:10,520 --> 00:03:15,200 And since we're going to be generating this Abi on the client, we can add in some cool effects using 50 00:03:15,200 --> 00:03:16,580 the tween service. 51 00:03:22,880 --> 00:03:28,220 Now, what we could go ahead and do is get a reference to our player, which is players dot local player. 52 00:03:28,520 --> 00:03:33,410 I'm going to create a table to keep track of all of the different OBE models that we've generated on 53 00:03:33,410 --> 00:03:33,800 the map. 54 00:03:33,800 --> 00:03:37,220 We'll just call this table on map models. 55 00:03:38,190 --> 00:03:43,800 And then we want to keep track of the current or last part that we're going to continually generate 56 00:03:43,800 --> 00:03:44,910 models onto. 57 00:03:44,940 --> 00:03:48,600 So for example, the current part is going to be this one right here. 58 00:03:48,600 --> 00:03:53,760 And then once we generate an AB model, we need to update the part to be that ending part for whatever 59 00:03:53,760 --> 00:03:54,450 AB model. 60 00:03:54,450 --> 00:03:58,500 So if we look in our AB models they each have that little end part. 61 00:03:58,500 --> 00:04:01,800 And that's what we're going to constantly update that reference to. 62 00:04:01,830 --> 00:04:06,090 So that way we're generating our jobs in the correct order. 63 00:04:06,090 --> 00:04:08,250 So I'm just going to call this variable. 64 00:04:08,250 --> 00:04:09,750 We can just call it last part. 65 00:04:09,990 --> 00:04:15,090 And that's going to be equal to workspace dot Global Start which is the default. 66 00:04:16,180 --> 00:04:21,760 And then we're also going to want to keep track of what model we're currently checkpointed at. 67 00:04:21,760 --> 00:04:29,380 So when a player dies, right, we want to be able to move them to, uh, wherever they were last at. 68 00:04:29,380 --> 00:04:31,960 And we need to keep track of that so we can create a variable. 69 00:04:31,960 --> 00:04:33,880 I'm going to call it checkpoint model. 70 00:04:33,880 --> 00:04:36,280 And for now we're just going to set it to nil. 71 00:04:37,240 --> 00:04:40,990 Now we can go ahead and grab all of the Abi models in our game. 72 00:04:40,990 --> 00:04:42,370 So I'll call this children. 73 00:04:42,370 --> 00:04:45,730 And that's equal to replicated storage Abi models get children. 74 00:04:45,730 --> 00:04:51,190 Now the problem here is that this Get Children function is going to return an array of the children. 75 00:04:51,190 --> 00:04:55,120 But this array might be ordered differently between clients. 76 00:04:55,120 --> 00:05:01,240 And that means when we use a random number picker to grab random Abi models, it might be different 77 00:05:01,240 --> 00:05:02,170 between clients. 78 00:05:02,170 --> 00:05:08,200 So we need to make sure that between all of the clients in our game, these tables are ordered correctly, 79 00:05:08,200 --> 00:05:09,610 or they're ordered the same. 80 00:05:09,610 --> 00:05:13,090 And the way we can do that is by using the table dot sort function. 81 00:05:13,090 --> 00:05:19,510 We'll pass the table, which is children and then we need a function to compare uh, basically A and 82 00:05:19,510 --> 00:05:20,620 B two instances. 83 00:05:20,620 --> 00:05:24,250 And we're going to use the less than operator. 84 00:05:24,250 --> 00:05:26,140 So we'll pass our function. 85 00:05:26,140 --> 00:05:28,480 This will get passed a value a and b. 86 00:05:29,640 --> 00:05:35,550 And we need to return a boolean from this function to let the sort function know how to sort this table. 87 00:05:35,550 --> 00:05:41,940 So what we could do is we can compare a name if it's less than b dot name. 88 00:05:41,940 --> 00:05:47,190 So you can actually compare the names of strings using the less than operator. 89 00:05:47,190 --> 00:05:53,730 And it will return either true or false if A's name is less than B's name. 90 00:05:53,730 --> 00:06:01,170 So for example, if I go on to the command line, I can print out like uh, if let's say this string 91 00:06:01,170 --> 00:06:05,970 hello, let's say the string is greater than this other string of hello. 92 00:06:05,970 --> 00:06:09,480 So obviously not it's going to be false because they're the same. 93 00:06:09,480 --> 00:06:13,500 But maybe if I add a number in here then I hit enter. 94 00:06:13,530 --> 00:06:17,280 As you can see now this string is considered greater than this string. 95 00:06:17,580 --> 00:06:20,550 If I make this string have a larger number than this one. 96 00:06:20,550 --> 00:06:22,740 So if I put two in here and then I hit enter. 97 00:06:22,740 --> 00:06:26,490 As you can see now this string would be considered greater than this string. 98 00:06:26,490 --> 00:06:31,620 And since all of the above models are named the same and they just have different numbers, that means 99 00:06:31,620 --> 00:06:35,460 we'll be able to order them correctly between all of the different clients in our game. 100 00:06:35,460 --> 00:06:39,960 So this is super important to do when we're grabbing all of those children. 101 00:06:39,960 --> 00:06:44,100 Now, another thing to note is that each one of our models has an attribute called chance. 102 00:06:44,100 --> 00:06:49,200 And this is going to determine how often we would like to generate a particular hobby model. 103 00:06:49,200 --> 00:06:53,220 So the higher the number, the more likely this model is going to spawn. 104 00:06:53,220 --> 00:06:56,910 And the way we're going to determine that is we'll create a table. 105 00:06:56,910 --> 00:07:02,640 And based on the chance of that model, we'll insert however many references to the model. 106 00:07:02,640 --> 00:07:05,700 So for example hobby model one has a chance of ten. 107 00:07:05,700 --> 00:07:10,920 So that means we're going to insert ten references in a table to hobby model one. 108 00:07:10,920 --> 00:07:14,010 Whereas hobby model ten is only going to have one reference. 109 00:07:14,010 --> 00:07:18,210 So we'll have a higher chance of spawning this model over this model. 110 00:07:18,210 --> 00:07:22,980 So to do that I'm going to create a table and we're going to call it hobby models. 111 00:07:23,690 --> 00:07:27,530 And then we're going to loop through every single model that we grabbed in here. 112 00:07:27,530 --> 00:07:29,000 So in children. 113 00:07:29,810 --> 00:07:34,220 And what we want to do is we want to go ahead and get the chance from this model. 114 00:07:34,220 --> 00:07:36,920 So that will be equal to model get attribute chance. 115 00:07:36,920 --> 00:07:42,530 And just in case our model doesn't have the attribute on it, then we'll set a default of one. 116 00:07:43,070 --> 00:07:47,900 And then once we get the chance from that model, we can go ahead and loop. 117 00:07:49,500 --> 00:07:55,680 Through however many times the chances, and then we'll just insert inside of our models table this 118 00:07:55,680 --> 00:07:56,820 particular model. 119 00:07:56,820 --> 00:08:00,000 So if the chance is ten, then we're inserting ten references. 120 00:08:00,000 --> 00:08:02,850 If the chance is one, then we're only inserting one reference. 121 00:08:03,360 --> 00:08:06,120 Now we can go ahead and create our random number generators. 122 00:08:06,120 --> 00:08:10,650 I'm going to call this first one random Hobby picker. 123 00:08:10,650 --> 00:08:16,470 So this one is going to be responsible for randomly grabbing models out of our hobby models folder. 124 00:08:16,470 --> 00:08:17,730 So random dot new. 125 00:08:17,730 --> 00:08:20,010 And then we need to go ahead and pass our seed here. 126 00:08:20,010 --> 00:08:23,910 So that's replicated storage dot c dot value. 127 00:08:24,490 --> 00:08:27,820 And then I'm going to need another random number generator. 128 00:08:27,820 --> 00:08:30,790 I'm just going to call this one random number picker. 129 00:08:31,720 --> 00:08:34,180 And that's equal to random dot new. 130 00:08:34,180 --> 00:08:37,330 And we'll pass the same seed as well. 131 00:08:37,360 --> 00:08:43,870 And the reason I want to separate random number generators is that in case I need to generate any other 132 00:08:43,870 --> 00:08:49,600 random numbers relating to like maybe setting the position of something randomly or whatever, then 133 00:08:49,600 --> 00:08:53,980 I want to do it in a separate number picker, and I don't want to affect the one that's going to be 134 00:08:53,980 --> 00:09:00,460 selecting the numbers, because when we randomly generate numbers, it's going to be in order. 135 00:09:00,460 --> 00:09:05,650 So when we pass a seed and we grab the first ten randomly generated numbers, they're always going to 136 00:09:05,650 --> 00:09:06,400 be the same. 137 00:09:06,400 --> 00:09:12,100 However, if we influence it by picking a random number that's not related to grabbing a particular 138 00:09:12,100 --> 00:09:16,240 hobby, then it might get messed up between clients. 139 00:09:16,570 --> 00:09:18,400 So for example here. 140 00:09:19,390 --> 00:09:25,540 If I had a for loop where I decided to print out ten random numbers and we're just going to do math 141 00:09:25,540 --> 00:09:26,620 dot random. 142 00:09:28,390 --> 00:09:33,340 And before we do that, we're going to set Math.random seed equal to like one. 143 00:09:34,180 --> 00:09:35,830 If I do this. 144 00:09:37,020 --> 00:09:37,290 Oops. 145 00:09:37,290 --> 00:09:40,770 Let me actually print the value out in the console. 146 00:09:40,770 --> 00:09:44,280 So if we do this there, we get our ten random numbers. 147 00:09:44,280 --> 00:09:48,660 And if I do it again, as you can see, the random numbers are exactly the same as the previous. 148 00:09:48,660 --> 00:09:55,650 However, if there was some random call of Math.random before this loop happened and I hit enter. 149 00:09:55,920 --> 00:10:02,220 As you can see now the numbers are a bit off because we made a call previous before, the actual numbers 150 00:10:02,220 --> 00:10:04,290 we wanted to randomly generate appeared. 151 00:10:04,290 --> 00:10:07,350 So we want to create two separate number pickers. 152 00:10:07,350 --> 00:10:11,700 This one's sole purpose is for randomly picking OBE models, right? 153 00:10:12,250 --> 00:10:18,100 And now we can go ahead and create a couple constants to tell us the threshold for how far away the 154 00:10:18,100 --> 00:10:21,130 player can be to generate models. 155 00:10:21,130 --> 00:10:24,550 So we'll call this constant generation distance. 156 00:10:24,850 --> 00:10:27,310 And we'll set it to a default of like 100 studs. 157 00:10:27,550 --> 00:10:33,280 Now another thing I want to do is that once a player starts getting far away from previous models. 158 00:10:33,280 --> 00:10:38,950 So as they're going through the Abbey, any models that were previously generated, we want to go ahead 159 00:10:38,950 --> 00:10:41,470 and destroy so we can create another constant. 160 00:10:41,470 --> 00:10:44,290 I'm going to call this destroy distance. 161 00:10:44,290 --> 00:10:47,320 And we can either set it to 100 or maybe a little bit farther away. 162 00:10:47,320 --> 00:10:49,450 We could do like 120 studs. 163 00:10:50,690 --> 00:10:53,390 Now we can go ahead and create a couple functions. 164 00:10:53,390 --> 00:10:56,990 One, we'll have to generate an RGB model. 165 00:10:58,580 --> 00:11:02,840 And then we could have another one to destroy an RB model. 166 00:11:04,710 --> 00:11:11,130 And then we're also going to need a function to constantly execute, to check how far away our player 167 00:11:11,130 --> 00:11:13,500 is from the last generated RB model. 168 00:11:13,500 --> 00:11:16,680 And we can connect that to like the heartbeat event and run service. 169 00:11:16,680 --> 00:11:19,290 So we could call this function on heartbeat. 170 00:11:20,950 --> 00:11:24,940 And then we'll check in here the distance of the player away from the last hobby. 171 00:11:24,940 --> 00:11:25,570 Model. 172 00:11:26,090 --> 00:11:31,370 So inside of the start function, what we'll do is we'll refer to the heartbeat event. 173 00:11:32,120 --> 00:11:36,110 And we'll go ahead and connect our on heartbeat function to that event. 174 00:11:36,260 --> 00:11:40,790 And inside of here, what we want to check is first off if the player has a character. 175 00:11:40,970 --> 00:11:44,240 So if they don't have a character then we're just going to return. 176 00:11:45,280 --> 00:11:49,330 Otherwise, we can check if the player's character. 177 00:11:49,330 --> 00:11:54,490 We'll use the get pivot function, which will get the position of the humanoid root part. 178 00:11:54,490 --> 00:12:01,660 If the position of that and we subtract that by the last part dot position, we get the magnitude. 179 00:12:02,450 --> 00:12:04,340 So we'll wrap this in parentheses. 180 00:12:04,700 --> 00:12:08,210 If this is greater than the generation distance. 181 00:12:08,210 --> 00:12:12,860 So if the player is too far away to generate any hobby models, then we're just going to return and 182 00:12:12,860 --> 00:12:13,730 not do anything. 183 00:12:13,760 --> 00:12:19,070 Otherwise we can go ahead and call our generate hobby model function to generate a new hobby model on 184 00:12:19,070 --> 00:12:19,640 the map. 185 00:12:20,210 --> 00:12:25,040 And what we can do in here is we can go ahead and pick a random model to generate. 186 00:12:25,040 --> 00:12:27,350 So we'll create a random number. 187 00:12:27,350 --> 00:12:28,430 We'll call it random int. 188 00:12:28,430 --> 00:12:31,670 And that's going to be equal to our random hobby picker. 189 00:12:31,670 --> 00:12:37,160 And we're going to go ahead and get a random integer which is going to be between one. 190 00:12:37,160 --> 00:12:42,170 And however many models are inside of the hobby models table. 191 00:12:42,620 --> 00:12:48,140 And then we can go ahead and get a random number from hobby models, index it with random int, and 192 00:12:48,140 --> 00:12:50,090 then we can go ahead and clone that model. 193 00:12:50,540 --> 00:12:56,180 And now with this new cloned model, we want to go ahead and update the key frame of it to be to wherever 194 00:12:56,180 --> 00:12:57,740 the last part was at. 195 00:12:57,740 --> 00:13:01,100 So for example, in the beginning this is going to be our last part. 196 00:13:01,100 --> 00:13:04,970 So we want to update the pivot of the model equal to this part. 197 00:13:04,970 --> 00:13:12,080 So for example with hobby model zero here we're going to update the position of this part to be equal 198 00:13:12,080 --> 00:13:13,100 to this part. 199 00:13:13,100 --> 00:13:15,980 And that means we're going to update last part equal to this one. 200 00:13:15,980 --> 00:13:20,090 So we can continually chain all of the different models together. 201 00:13:20,850 --> 00:13:23,790 So we'll refer to our model call the pivot. 202 00:13:24,500 --> 00:13:27,710 Two function and it doesn't know this is a model. 203 00:13:27,710 --> 00:13:30,020 So we can like quickly denote it as a model. 204 00:13:30,020 --> 00:13:31,670 So we'll call pivot two. 205 00:13:31,670 --> 00:13:36,350 And the key frame is going to be equal to whatever the last part dot key frame is. 206 00:13:37,060 --> 00:13:43,120 And then we also want to go ahead and just hide those parts that are inside of the model, the starting 207 00:13:43,120 --> 00:13:43,900 and ending part. 208 00:13:43,900 --> 00:13:50,470 So we can just refer to the start part inside of the model and set the transparency equal to one. 209 00:13:50,470 --> 00:13:53,320 We'll make sure that can collide is off for it as well. 210 00:13:53,320 --> 00:13:55,930 So can collide is equal to false. 211 00:13:56,110 --> 00:13:59,740 And then those parts also have a decal in it which we can go ahead and delete. 212 00:13:59,740 --> 00:14:08,620 So model dot start will find first child which is a decal just in case you name the decal differently. 213 00:14:08,620 --> 00:14:10,360 And then we'll destroy the decal. 214 00:14:10,540 --> 00:14:17,170 And then we can do this as well for the end part that is in our models as well. 215 00:14:18,800 --> 00:14:22,100 We'll just copy that, paste that there and paste that there. 216 00:14:23,130 --> 00:14:28,620 And now, if we want to be a little fancy with how we spawn these models in, then we can go ahead and 217 00:14:28,620 --> 00:14:30,780 use something like the tween service. 218 00:14:30,780 --> 00:14:35,820 And we could maybe like displace all of the parts in the model to be like far away. 219 00:14:35,820 --> 00:14:41,610 And then we could tween them in like, it looks like they're materializing out of the air and then floating 220 00:14:41,610 --> 00:14:44,430 into their correct positions, which would look kind of cool. 221 00:14:44,490 --> 00:14:50,880 So to do that, we could loop through every single descendant inside of our model, so we'll get descendants. 222 00:14:51,780 --> 00:14:56,940 And we want to do is we want to first make sure that this descendant is a base part, and we also want 223 00:14:56,940 --> 00:15:00,090 to make sure it's not the start or ending part. 224 00:15:00,090 --> 00:15:03,630 So if this descendants name is equal to start. 225 00:15:04,350 --> 00:15:09,630 Or if the descendants name is equal to, and then we'll just return. 226 00:15:09,750 --> 00:15:13,140 If the descendant is not a base part. 227 00:15:14,200 --> 00:15:15,370 Then we'll return as well. 228 00:15:15,370 --> 00:15:19,660 So if not is a bass part then we'll return. 229 00:15:20,590 --> 00:15:24,940 And actually, since this is a for loop, we don't want to use return, we want to use continue. 230 00:15:24,970 --> 00:15:25,630 My bad. 231 00:15:25,660 --> 00:15:30,340 So we want to continue to the next descendant inside of our model. 232 00:15:30,970 --> 00:15:37,300 But once we verified it's a part and it's not the starting or ending part, then to keep track of its 233 00:15:37,300 --> 00:15:40,810 original key frame, we'll set an attribute on this descendant. 234 00:15:41,050 --> 00:15:45,910 We'll call it a ridge key frame, and that's going to be equal to the descendant key frame. 235 00:15:47,090 --> 00:15:51,110 And then we can also set an attribute of let's say it's transparency. 236 00:15:51,110 --> 00:15:53,000 So we want to make all the parts invisible. 237 00:15:53,000 --> 00:15:57,020 And then we want them to fade in as well as move into their correct position. 238 00:15:57,020 --> 00:15:58,400 So we'll set an attribute on it. 239 00:15:58,400 --> 00:16:01,160 We'll call it original transparency. 240 00:16:01,160 --> 00:16:04,040 And that's going to be equal to the descendants transparency. 241 00:16:04,790 --> 00:16:10,340 And then we can go ahead and update the keyframe of this descendant to some kind of random keyframe. 242 00:16:10,340 --> 00:16:14,480 So we'll do descendant keyframe and then we'll offset it with a new vector three. 243 00:16:14,480 --> 00:16:16,280 So vector three dot new. 244 00:16:16,280 --> 00:16:20,450 And then this is where we're going to use our random number picker to generate some random numbers. 245 00:16:20,450 --> 00:16:26,120 So like next integer we could do maybe an offset of up to eight studs away. 246 00:16:26,120 --> 00:16:29,780 So either negative eight or positive eight for the x axis. 247 00:16:30,980 --> 00:16:34,400 And then we'll just copy that and do it for the other axes. 248 00:16:35,480 --> 00:16:41,090 So now we've set the C frame of our part somewhere random, and then we'll update the transparency to 249 00:16:41,090 --> 00:16:42,230 make it invisible. 250 00:16:43,010 --> 00:16:50,120 And now we can go ahead and use the tween service to go ahead and tween the transparency as well as 251 00:16:50,120 --> 00:16:52,850 the keyframe for our descendant. 252 00:16:52,850 --> 00:16:55,880 So we'll do a tween info dot new. 253 00:16:55,910 --> 00:17:01,820 Maybe we'll tween it for like one second, and then you can really choose any type of easing style you 254 00:17:01,820 --> 00:17:02,480 would like. 255 00:17:02,480 --> 00:17:04,700 I'll just pick quad for this one. 256 00:17:05,090 --> 00:17:10,010 And then for our goal table we want to go ahead and update the keyframe. 257 00:17:10,720 --> 00:17:11,860 Equal to. 258 00:17:11,860 --> 00:17:14,980 And we're going to get that original sea frame property. 259 00:17:14,980 --> 00:17:18,100 So get attribute a ridge sea frame. 260 00:17:18,250 --> 00:17:22,240 And then we also want to go ahead and update the transparency as well. 261 00:17:22,420 --> 00:17:30,520 And it's going to be equal to the descendant get attribute um a ridge transparency. 262 00:17:30,880 --> 00:17:33,370 And then we can just go ahead and play that tween. 263 00:17:33,920 --> 00:17:35,960 Now this is going to be tweening. 264 00:17:36,230 --> 00:17:36,800 Um. 265 00:17:37,630 --> 00:17:41,380 Not in the workspace because we haven't parented to the workspace yet. 266 00:17:41,380 --> 00:17:46,810 So once we start playing the tween, then we want to go ahead and immediately parent the model equal 267 00:17:46,810 --> 00:17:50,230 to the workspace, and we're going to put it in the models folder. 268 00:17:51,000 --> 00:17:56,730 And then once we've generated this new OB model, we can go ahead and update our last part variable 269 00:17:56,730 --> 00:17:58,470 to be equal to model. 270 00:17:58,470 --> 00:17:59,880 And we'll get the end part. 271 00:17:59,880 --> 00:18:04,380 So that way when we generate the next OB model we're going to set it to the correct key frame. 272 00:18:05,120 --> 00:18:07,550 So now we have this kind of basic system set up. 273 00:18:07,550 --> 00:18:10,070 Let's go ahead and actually test out to see if it works. 274 00:18:10,070 --> 00:18:14,810 So if we go and play test we should be within 100 studs of that part. 275 00:18:14,810 --> 00:18:19,040 And we are getting an error because of a problem. 276 00:18:19,040 --> 00:18:20,600 And that's because. 277 00:18:21,410 --> 00:18:26,480 For some reason I use tween service and not tween info, so we'll fix that and let's try that one more 278 00:18:26,480 --> 00:18:27,200 time. 279 00:18:29,030 --> 00:18:29,930 Okay, there we go. 280 00:18:29,930 --> 00:18:32,660 Just like that, because we are within 100 studs of this part. 281 00:18:32,690 --> 00:18:37,910 It generated the first A.B. model since we were within 100 studs of that newly updated part. 282 00:18:37,940 --> 00:18:39,170 It generated the second. 283 00:18:39,170 --> 00:18:46,460 And since we were still within 100 studs of that last part, it generated a third A.B. model. 284 00:18:46,460 --> 00:18:52,190 And then if we go ahead and walk closer, as you can see now, it's continuing to generate new A.B. 285 00:18:52,190 --> 00:18:55,880 models, and we can go ahead and keep walking and keep walking. 286 00:18:55,880 --> 00:18:59,510 And it's going to continually generate these A.B. models. 287 00:18:59,510 --> 00:19:04,880 So now that we've got this basic generation system set up, we want to go ahead and start deleting these 288 00:19:04,880 --> 00:19:09,050 other A.B. models behind us as we get farther and farther away. 289 00:19:09,080 --> 00:19:14,360 And each time we walk through these different models, we want to go ahead and update that variable 290 00:19:14,360 --> 00:19:16,130 for whatever our last checkpoint was. 291 00:19:16,130 --> 00:19:22,130 So that way when the player dies, we can go ahead and move their character over to wherever their last 292 00:19:22,130 --> 00:19:23,330 checkpoint was at. 293 00:19:23,420 --> 00:19:26,360 But so far, our RB generation is working great. 294 00:19:26,360 --> 00:19:31,820 You can see that all of the models are just kind of floating in and forming in together, so it looks 295 00:19:31,820 --> 00:19:32,780 really cool. 296 00:19:33,880 --> 00:19:39,370 Okay, so now what we want to do is when we get far enough away from a previous model, we want to go 297 00:19:39,370 --> 00:19:40,840 ahead and destroy it. 298 00:19:40,840 --> 00:19:48,250 So to keep track of that, we need to go ahead and insert any model we generate into that on map models 299 00:19:48,250 --> 00:19:48,760 table. 300 00:19:48,760 --> 00:19:55,330 So after we have cloned an RB model, then we can go ahead and insert this model into our on map models 301 00:19:55,330 --> 00:19:56,020 table. 302 00:19:56,530 --> 00:20:03,220 So that means the first instance inside of our on map models table is going to be the RB model that 303 00:20:03,220 --> 00:20:06,070 will be farthest away from our player. 304 00:20:06,070 --> 00:20:10,060 So what we can do is we can check if we have generated any models. 305 00:20:10,060 --> 00:20:16,780 So we'll check if in the first index of our on map models table, a value exists there. 306 00:20:16,780 --> 00:20:23,830 And we want to make sure that the player dot character will get the position of our player. 307 00:20:24,470 --> 00:20:32,330 And we subtract that from our own map models get the first model, we'll get the end part and get its 308 00:20:32,330 --> 00:20:35,240 position, and we'll check the magnitude. 309 00:20:35,950 --> 00:20:37,810 Between these two vectors. 310 00:20:37,810 --> 00:20:48,370 So if the player is greater than our destroyed distance away, then that means we can go ahead and destroy 311 00:20:48,370 --> 00:20:49,720 this model. 312 00:20:49,990 --> 00:20:54,490 So we could call our function destroy OB model, and we could pass the model here. 313 00:20:54,490 --> 00:20:56,770 So it would be our on map models. 314 00:20:56,770 --> 00:20:59,080 Get that model at the first index. 315 00:20:59,760 --> 00:21:04,800 And then once we destroy it, we can go ahead and remove it out of our on map models table. 316 00:21:04,800 --> 00:21:11,340 So we'll use table dot remove from on map models and remove the model at the first index. 317 00:21:11,850 --> 00:21:16,860 Now inside of our Destroyable model, we can basically do the exact same thing that we did up here, 318 00:21:16,860 --> 00:21:18,120 but in reverse. 319 00:21:18,120 --> 00:21:22,890 So instead we'll tween all of the parts to go out randomly and then fade away. 320 00:21:22,890 --> 00:21:26,610 And then once that's tween is completed, then we can go ahead and destroy the model. 321 00:21:26,610 --> 00:21:30,570 So I'm just going to copy this for loop and paste it in here. 322 00:21:31,610 --> 00:21:38,000 And we'll basically do the exact same thing where we check for whether or not it was the start or ending 323 00:21:38,000 --> 00:21:40,190 part, and we'll make sure it's a base part. 324 00:21:40,190 --> 00:21:41,990 And then once we do that. 325 00:21:42,540 --> 00:21:50,910 We don't have to do any of this, but instead we're going to tween the C frame equal to a random C frame. 326 00:21:50,910 --> 00:21:56,490 And we want to set the transparency equal to be completely transparent or the value of one. 327 00:21:57,000 --> 00:22:01,590 So for the c frame here we can literally just set it to the descendant C frame. 328 00:22:02,460 --> 00:22:07,170 And then offset it again by a random vector three, which we've done up here. 329 00:22:07,170 --> 00:22:11,700 So I'll literally just copy this and then we'll just paste that there. 330 00:22:11,700 --> 00:22:18,870 So now we're creating a tween to randomly move this part away while it fades out. 331 00:22:18,870 --> 00:22:20,790 And then we play that tween. 332 00:22:20,790 --> 00:22:25,860 And then once we've done that for all of the descendants in the model, we'll go ahead and delay a function 333 00:22:25,860 --> 00:22:30,960 for the duration of this tween, which is one second if you want to make it longer. 334 00:22:30,960 --> 00:22:32,130 Actually, let's go ahead and make it longer. 335 00:22:32,130 --> 00:22:36,390 We'll do two seconds, so we'll delay a function for two seconds. 336 00:22:37,320 --> 00:22:41,790 And at this point, all of the parts inside of our model should be completely transparent. 337 00:22:41,790 --> 00:22:44,910 So we should be able to destroy the model. 338 00:22:45,680 --> 00:22:46,700 And that's it. 339 00:22:46,730 --> 00:22:53,030 We destroy the model, we fade it out, and then we remove it from our on map models table. 340 00:22:53,390 --> 00:22:56,120 So if we go and play test the game this time. 341 00:22:57,430 --> 00:23:03,580 And we began to walk along our, uh, generated orb. 342 00:23:03,730 --> 00:23:10,120 Once we get far enough away from the first orb model, it should go ahead and fade out. 343 00:23:10,150 --> 00:23:11,680 Tween out and then get destroyed. 344 00:23:11,680 --> 00:23:15,130 So just like that, it faded away and now it's gone. 345 00:23:15,130 --> 00:23:19,480 And that means the new updated value at the first index is going to be this model. 346 00:23:19,480 --> 00:23:23,950 And once we get far enough away from that one, as you can see, it fades and disappears. 347 00:23:23,950 --> 00:23:28,690 The next one will be that one fades and disappears and so on and so forth. 348 00:23:28,690 --> 00:23:36,220 Now problem with this is that if I were to accidentally die and like fall off the map, as you can see, 349 00:23:36,220 --> 00:23:43,570 all of our models have disappeared and now we're stuck at spawn and we can't generate any more models. 350 00:23:43,570 --> 00:23:49,240 So this means we're going to have to keep track of what model we are checkpointed at. 351 00:23:49,240 --> 00:23:56,170 And if that model, when we look through our on map models table, if the model at the first index in 352 00:23:56,200 --> 00:24:00,400 that table is equal to our checkpoint model, then we don't want to destroy it. 353 00:24:01,030 --> 00:24:07,270 What we want to go ahead and do is we want to go ahead and create a function to listen for when a checkpoint 354 00:24:07,270 --> 00:24:09,130 gets touched on a model. 355 00:24:09,940 --> 00:24:12,610 So we'll call this function on checkpoint. 356 00:24:13,620 --> 00:24:19,830 Touched and it'll get past whatever model is going to be the checkpoint, as well as the other part 357 00:24:19,830 --> 00:24:22,260 that touched that checkpoint part. 358 00:24:23,110 --> 00:24:28,930 And that means when we generate a new AB model, what we want to do is we want to listen for when that 359 00:24:28,930 --> 00:24:31,780 checkpoint part inside of our model gets touched. 360 00:24:31,780 --> 00:24:35,560 So we'll connect a function to that and get that other part. 361 00:24:35,560 --> 00:24:39,250 And then we'll call our on checkpoint touch function. 362 00:24:39,250 --> 00:24:43,570 We'll pass the model as well as the part that touched our checkpoint. 363 00:24:43,570 --> 00:24:46,810 And then we can go ahead and check if it was our player. 364 00:24:47,170 --> 00:24:55,720 So if players get player from character, if we pass other part dot parent, if that's not equal to 365 00:24:55,720 --> 00:24:59,050 our local player, then we're just going to return. 366 00:24:59,650 --> 00:25:04,930 Another thing we want to go ahead and check is if this model is already equal to our checkpoint model, 367 00:25:04,930 --> 00:25:07,300 then we'll just return because we don't care about it. 368 00:25:07,840 --> 00:25:14,080 Otherwise we can go ahead and update the value inside of our checkpoint model equal to this new model. 369 00:25:14,080 --> 00:25:15,790 So now we have this new checkpoint. 370 00:25:15,790 --> 00:25:23,050 So that means before we actually go and destroy an OB model, we want to make sure that whatever model 371 00:25:23,050 --> 00:25:28,450 is stored on this first index is not equal to our checkpoint. 372 00:25:28,900 --> 00:25:31,030 So if we have a model here. 373 00:25:31,940 --> 00:25:35,000 Then we want to also check if this model. 374 00:25:35,000 --> 00:25:38,150 So on map models get it at that first index. 375 00:25:38,150 --> 00:25:41,690 We want to make sure that it's not equal to our checkpoint model. 376 00:25:41,870 --> 00:25:44,360 And we want to make sure the player is far enough away. 377 00:25:44,360 --> 00:25:50,930 So if we have a model on the map and that model on our map is not equal to our checkpoint model and 378 00:25:50,930 --> 00:25:54,530 the player is far enough away from it, then we can go ahead and destroy it. 379 00:25:55,130 --> 00:25:57,350 So now if we go and play test our game. 380 00:25:59,060 --> 00:26:02,660 As we go through and touch these invisible parts in our model. 381 00:26:02,750 --> 00:26:06,680 The checkpoint is being updated to each of these models. 382 00:26:06,680 --> 00:26:09,620 So for example, our checkpoint is currently set to this model. 383 00:26:09,620 --> 00:26:18,020 So if I were to hop off and fall down, as you can see, this model previous to our checkpoint model 384 00:26:18,020 --> 00:26:18,980 got destroyed. 385 00:26:18,980 --> 00:26:23,690 But our checkpoint model and none of the models after our checkpoint model got destroyed. 386 00:26:24,260 --> 00:26:25,790 And that's what we want. 387 00:26:26,540 --> 00:26:30,830 Now, when the player dies, we need to, of course, go ahead and move the player's character over 388 00:26:30,830 --> 00:26:33,290 to that checkpoint model, which we'll do in a second. 389 00:26:33,290 --> 00:26:36,560 But there is another problem we want to take a look at. 390 00:26:36,560 --> 00:26:40,400 And that's let's say the player never touches a checkpoint. 391 00:26:40,400 --> 00:26:44,750 So for example, these three generated let's say I never touch this checkpoint part and I just fall 392 00:26:44,750 --> 00:26:45,620 off the map. 393 00:26:45,890 --> 00:26:51,560 Well now all those models just got destroyed and now I am screwed. 394 00:26:51,560 --> 00:26:54,680 And I can't play the game because they're not going to generate anymore. 395 00:26:55,310 --> 00:27:02,240 So to fix that problem, before we go and destroy an OBE model, we also want to make sure that a checkpoint 396 00:27:02,240 --> 00:27:06,920 model actually exists that the player can move their character to. 397 00:27:06,950 --> 00:27:11,600 So we want to make sure that we actually have a model on the map. 398 00:27:12,240 --> 00:27:17,820 And we want to make sure that we have a checkpoint model, and we want to make sure that model on the 399 00:27:17,820 --> 00:27:19,950 map is not equal to our checkpoint model. 400 00:27:19,950 --> 00:27:23,190 And we want to make sure that the player is far enough away. 401 00:27:23,190 --> 00:27:28,740 So if we match all of those different criteria, then we can go ahead and destroy the model. 402 00:27:28,740 --> 00:27:36,090 So now if I play the game, even though I don't have a model set as my checkpoint, because we have 403 00:27:36,090 --> 00:27:39,360 to verify if a checkpoint model actually exists. 404 00:27:39,360 --> 00:27:42,870 As you can see, these different models did not get destroyed. 405 00:27:42,870 --> 00:27:44,550 And now I've touched this model. 406 00:27:44,550 --> 00:27:45,840 It is set to my checkpoint. 407 00:27:45,840 --> 00:27:52,290 I touch this one, it's set to my checkpoint and so on and so forth as I progress along this RB. 408 00:27:53,100 --> 00:27:55,590 And the ones behind me should start to disappear. 409 00:27:55,590 --> 00:27:56,160 So there you go. 410 00:27:56,160 --> 00:27:57,780 That one deleted itself. 411 00:27:57,780 --> 00:27:59,520 That one deleted itself. 412 00:28:00,230 --> 00:28:06,920 And as I continue to walk along the map, they continue to destroy themselves, which is very, very 413 00:28:06,920 --> 00:28:07,460 cool. 414 00:28:08,060 --> 00:28:13,010 Now, another thing we want to do real quick, because you might have noticed that our RB generated 415 00:28:13,010 --> 00:28:21,050 the same even though we played the game two different times, is that when we generate this value here 416 00:28:21,050 --> 00:28:28,100 for our seed, we can go ahead and set the seed for this random number generator equal to, for example, 417 00:28:28,100 --> 00:28:29,510 the current tick. 418 00:28:29,810 --> 00:28:34,730 So the current tick will never be the same since this is constantly updating what time it is in the 419 00:28:34,730 --> 00:28:40,430 future, and that guarantees that our random number generator is always going to generate a random number 420 00:28:40,430 --> 00:28:43,220 for our seed, and it's never going to be the same. 421 00:28:43,370 --> 00:28:46,820 Now, since our number value is limited up to three decimals. 422 00:28:46,820 --> 00:28:51,890 If we would also like to use the real estate for whole numbers or integers as well. 423 00:28:51,890 --> 00:28:55,970 When we generate a random number here, we can go ahead and multiply this by some big random number. 424 00:28:55,970 --> 00:28:58,610 So you could just put in a random number here like that. 425 00:28:59,790 --> 00:29:05,100 And that means when you go and generate your random seed, if we go ahead and look in replicated storage 426 00:29:05,100 --> 00:29:08,760 and we take a look at our seed, now here's our randomly generated seed. 427 00:29:09,150 --> 00:29:10,830 And we go and we walk along. 428 00:29:10,830 --> 00:29:16,620 And now our map is being randomly generated, which is different from what we had last time. 429 00:29:16,950 --> 00:29:23,550 And if I stop and then I play test my game once again, and then we go ahead and look at our seed this 430 00:29:23,550 --> 00:29:26,340 time, as you can see, it's a completely different set of numbers. 431 00:29:26,340 --> 00:29:30,780 And now we are generating or hopefully we should be generating a different map, as you can see right 432 00:29:30,780 --> 00:29:31,350 here. 433 00:29:33,040 --> 00:29:34,900 And we'll test that again one last time. 434 00:29:35,560 --> 00:29:38,800 If we go and take a look at our seed, as you can see it's completely different. 435 00:29:38,800 --> 00:29:42,340 And now we are generating a different Abi once again. 436 00:29:43,640 --> 00:29:48,740 Okay, so the last thing we need to go ahead and do is we want to listen for when a new character is 437 00:29:48,740 --> 00:29:54,050 added to our player, and we want to move that player's character to the last checkpoint they were at. 438 00:29:54,080 --> 00:29:58,580 So inside of our initialize function, we can listen to when the player. 439 00:29:59,430 --> 00:30:05,490 Has a character added to them, and we'll connect a function to this and get that character. 440 00:30:06,290 --> 00:30:09,380 And actually we could go ahead and create a dedicated function for this. 441 00:30:09,380 --> 00:30:11,960 We'll call it on character added. 442 00:30:13,050 --> 00:30:18,600 And we'll get past the player's character here, so we'll actually connect on character added. 443 00:30:19,990 --> 00:30:23,260 And then we can go ahead and check if we have a checkpoint model. 444 00:30:23,260 --> 00:30:26,260 If we do not have a checkpoint model, then we'll just return. 445 00:30:26,710 --> 00:30:34,210 Otherwise, what we could do is we could like tween our player across the map to the checkpoint. 446 00:30:34,210 --> 00:30:38,110 So we'll get the player's route part, which is equal to their character. 447 00:30:38,110 --> 00:30:44,860 And we're going to go ahead and wait for child humanoid route part, because there's no guarantee all 448 00:30:44,860 --> 00:30:49,210 of the descendants of this player's character will be replicated immediately. 449 00:30:49,480 --> 00:30:52,630 And then we'll go ahead and anchor the route part. 450 00:30:54,540 --> 00:30:56,460 And then we'll create a tween. 451 00:30:57,330 --> 00:30:59,250 On our route part. 452 00:31:00,060 --> 00:31:01,770 We'll do a tween info. 453 00:31:03,130 --> 00:31:06,580 New between for like three seconds. 454 00:31:06,580 --> 00:31:08,800 And we'll pick an easy style of like sign. 455 00:31:08,800 --> 00:31:14,020 And we want to go ahead and update the C frame of our players humanoid root part. 456 00:31:17,600 --> 00:31:20,000 And that's going to be equal to the checkpoint model. 457 00:31:20,180 --> 00:31:27,950 And inside of each of our models we have another part which is our respawn point. 458 00:31:27,950 --> 00:31:33,350 And we're going to go ahead and set the keyframe of our player's humanoid part to that respawn point. 459 00:31:33,350 --> 00:31:38,960 So checkpoint model dot respawn point dot keyframe. 460 00:31:40,610 --> 00:31:46,850 And now that we have this new tween, we can go ahead and play it and then we'll wait for this tween 461 00:31:46,970 --> 00:31:48,020 to complete. 462 00:31:48,020 --> 00:31:52,190 So completed we'll actually connect a function to it. 463 00:31:52,580 --> 00:32:00,020 And then we'll go ahead and set dot anchored equal to false on our root part. 464 00:32:01,000 --> 00:32:02,770 So now if we go and play test the game. 465 00:32:04,210 --> 00:32:11,350 If we start walking along the course or this abbey and we're updating. 466 00:32:11,350 --> 00:32:16,690 So right now the checkpoint should be set to this model if my player were to fall off the map. 467 00:32:17,330 --> 00:32:21,320 And I die now when the player's character gets added. 468 00:32:21,350 --> 00:32:25,400 I should be tweened to the new checkpoint just like that. 469 00:32:25,400 --> 00:32:31,190 And now we are back in our obby and we can continue along the course. 470 00:32:32,950 --> 00:32:39,310 The map is continually generated in front of us, while the previous, uh, models behind us are going 471 00:32:39,310 --> 00:32:41,050 to be destroyed just like that. 472 00:32:41,830 --> 00:32:43,930 And we continually update the checkpoint. 473 00:32:43,930 --> 00:32:46,120 And if I were to somehow die. 474 00:32:47,090 --> 00:32:48,530 And fall out of the world. 475 00:32:48,530 --> 00:32:50,480 It doesn't destroy those checkpoints that we're at. 476 00:32:50,480 --> 00:32:53,630 And I get tweened to wherever I was last at. 477 00:32:53,630 --> 00:32:54,470 Very cool. 478 00:32:56,860 --> 00:33:02,290 And of course, this RB generation is working, even though we have two separate players here, because 479 00:33:02,290 --> 00:33:06,730 both of these players are using the same seed for the random number generator, they're going to be 480 00:33:06,730 --> 00:33:07,990 generating the same RB. 481 00:33:08,080 --> 00:33:11,920 So if I have this player walk down and fill in more stuff here. 482 00:33:12,070 --> 00:33:14,710 As you can see, we get a feel for what the pattern looks like. 483 00:33:14,710 --> 00:33:21,400 We have two islands and then a bridge and then another two islands, and then this player should generate 484 00:33:21,400 --> 00:33:22,540 the exact same thing. 485 00:33:22,540 --> 00:33:26,170 So as you can see two islands, a bridge and then the other two islands. 486 00:33:26,170 --> 00:33:27,370 And if I continue. 487 00:33:27,400 --> 00:33:32,290 Looks like we get one of those islands that turns 90 degrees, and we get another bridge and another 488 00:33:32,290 --> 00:33:32,890 island. 489 00:33:32,890 --> 00:33:35,590 And this player should generate the exact same thing. 490 00:33:35,590 --> 00:33:40,120 And as you can see, we get the exact same models and the exact same setup for our map. 491 00:33:40,120 --> 00:33:46,090 That's because both of these players are using the same, uh, seed for their random number generator. 492 00:33:47,350 --> 00:33:53,470 Now that we have the basic foundation for our project set up, we can go ahead and start adding more 493 00:33:53,470 --> 00:33:56,080 features in the next lectures. 494 00:33:57,280 --> 00:33:58,030 See you there.